package com.wyw.learning.thread.collections.copyonwrite;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * CopyOnWriteArrayList
 *  代替Vector和SynchronizedList，就和ConcurrentHashMap代替SynchronizedMap的原因一样
 *  Vector和SynchronizedList的锁的粒度太大，并发效率相对比较低，并且迭代是无法编辑
 *  Copy-On-Write并发容器还包括CopyOnWriteArraySet，用来代替同步Set
 *
 * 使用场景
 *  读操作可以尽可能地快，而写操作即使慢一些页没有太大关系
 *      读多写少：黑名单，每日更新；监听器，迭代操作远多于修改操作
 *
 * 读写规则
 *  读写锁（写写互斥、读写互斥、写读互斥）的规则升级：读取是完全不加锁的，并且写入不会阻塞读取操作。只有写入与写入之间需要进行同步等待
 *  因为是创建了一个新的副本，这样虽然会有过期数据的情况，但是可以读和写是在不同的容器
 *  "不可变"原理    因为是创建的一个新的容器，那么旧的容器就是不可变的
 *  迭代的时候，如果数组元数据已经修改过了，迭代器是不知道的，读的是旧数组
 *
 * 缺点
 *  数据不一致性问题：CopyOnWrite容器只能保证数据的最终一致性，不能保证数据的实时一致性。所以如果希望写入的数据立刻能读到，请不要使用CopyOnWrite容器
 *  内存占用问题：因为CopyOnWrite的写是复制机制，所以在进行写操作的时候，内存里会同时驻扎两个对象的内存
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * 演示CopyOnWriteArrayList可以在迭代的过程中修改数组内容，但是ArrayList不行，对比
 *  参考    https://stackoverflow.com/questions/19103123/copyonarraylist-concurrent-modification
 *         https://howtodoinjava.com/java/collections/java-copyonwritearrayset/
 * Update History:
 * Author        Time            Content
 */
public class CopyOnWriteArrayListDemo1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
//        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");

        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
            System.out.println("list is" + list);
            String next = iterator.next();
            System.out.println(next);

            if (next.equals("2")) {
                list.remove("5");
            }
            if (next.equals("3")) {
                list.add("3 found");
            }
        }
    }
}
